package com.zhangzhan.gulimallcart.service.impl;

import com.alibaba.fastjson.JSON;
import com.zhangzhan.gulimallcart.feign.ProductFeignService;
import com.zhangzhan.gulimallcart.interceptor.TempOrInfoUserInterceptor;
import com.zhangzhan.gulimallcart.service.CartService;
import com.zhangzhan.gulimallcart.tos.SkuInfoTo;
import com.zhangzhan.gulimallcart.tos.TempOrInfoUserTo;
import com.zhangzhan.gulimallcart.vos.CartItemVo;
import com.zhangzhan.gulimallcart.vos.CartVo;
import com.zhangzhan.gulimallcommcon.util.MyCollUtil;
import com.zhangzhan.gulimallcommcon.util.R;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.BoundHashOperations;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ThreadPoolExecutor;

import static com.zhangzhan.gulimallcommcon.constant.CartConstant.CART_REDIS_HASH_KEY;

/**
 * @author 张一恒
 * @version 1.0
 * @description:
 * @date 2024/6/29 6:28
 */
@Service
public class CartServiceImpl implements CartService {

    @Autowired
    private StringRedisTemplate stringRedisTemplate;
    @Autowired
    private ProductFeignService productFeignService;

    @Autowired
    private ThreadPoolExecutor executor;

    @Override
    public CartItemVo addCart(Long skuId, Integer num, Boolean merge, CartItemVo tempItem) throws ExecutionException, InterruptedException {
        //购物车信息存在redis中，判断当前是否登录状态，如果没有登录使用临时用户的user-key作为key
        BoundHashOperations<String, Object, Object> ops = getHashOps();

        //查询如果保存的有数据了就改变商品数量和商品总价
        Object cacheSkuInfo = ops.get(skuId.toString());
        if (Objects.isNull(cacheSkuInfo)) {
            CartItemVo vo = new CartItemVo();
            if (!merge) {
                //组装第一次加入购物车的商品信息
                CompletableFuture<Void> getSkuInfo = CompletableFuture.runAsync(() -> {
                    //远程调用查询sku信息
                    R r = productFeignService.skuInfo(skuId);
                    if (r.getCode() != 0) {
                        throw new RuntimeException("系统异常");
                    }
                    SkuInfoTo skuInfoTo = JSON.parseObject(r.getData(), SkuInfoTo.class);
                    vo.setCount(num);
                    vo.setImage(skuInfoTo.getSkuDefaultImg());
                    vo.setPrice(skuInfoTo.getPrice());
                    vo.setTitle(skuInfoTo.getSkuName());
                    vo.setSkuId(skuInfoTo.getSkuId());
                }, executor);

                CompletableFuture<Void> getSkuAttrs = CompletableFuture.runAsync(() -> {
                    //获取skuAttr信息
                    R r2 = productFeignService.skuAttrs(skuId);
                    if (r2.getCode() != 0) {
                        throw new RuntimeException("系统异常");
                    }
                    List<String> attrs = JSON.parseObject(r2.getData(), List.class);
                    if (MyCollUtil.isNotEmpty(attrs)) {
                        vo.setSkuAttrs(attrs);
                    }
                }, executor);

                CompletableFuture.allOf(getSkuInfo, getSkuAttrs).get();

                ops.put(skuId.toString(), JSON.toJSONString(vo));
                return vo;
            } else {

                ops.put(skuId.toString(), JSON.toJSONString(tempItem));
                return tempItem;
            }

        } else {
            //修改后合并
            CartItemVo cartItemVo = JSON.parseObject(cacheSkuInfo.toString(), CartItemVo.class);
            cartItemVo.setCount(cartItemVo.getCount() + num);
            String jsonString = JSON.toJSONString(cartItemVo);
            ops.put(skuId.toString(), jsonString);
            return cartItemVo;
        }
    }

    /**
     * @param skuId
     * @return com.zhangzhan.gulimallcart.vos.CartItemVo
     * @description 查询缓存中数据
     * @author zhangyiheng
     * @date 2024/6/29 11:06
     */
    @Override
    public CartItemVo getCacheCart(Long skuId) {
        BoundHashOperations<String, Object, Object> ops = getHashOps();

        Object cacheSkuInfo = ops.get(skuId.toString());
        if (!Objects.isNull(cacheSkuInfo)) {
            return JSON.parseObject(cacheSkuInfo.toString(), CartItemVo.class);
        }

        return null;

    }

    /**
     * @return com.zhangzhan.gulimallcart.vos.CartVo
     * @description 用户点击购物车合并购物车内容
     * @author zhangyiheng
     * @date 2024/6/29 11:13
     */
    @Override
    public CartVo cartList() throws ExecutionException, InterruptedException {
        TempOrInfoUserTo tempOrInfoUserTo = TempOrInfoUserInterceptor.threadLocal.get();
        CartVo cartVo = new CartVo();
        List<CartItemVo> cartItemVos = new ArrayList<>();
        //如果已登录合并
        if (!Objects.isNull(tempOrInfoUserTo.getUserId())) {
            //判断临时用户购物车是否有内容
            String userKey = CART_REDIS_HASH_KEY + tempOrInfoUserTo.getUserKey();
            BoundHashOperations<String, Object, Object> tempOps = stringRedisTemplate.boundHashOps(userKey);
            List<Object> tempCarts = tempOps.values();
            if (MyCollUtil.isNotEmpty(tempCarts)) {
                //有
                List<CartItemVo> tempCartItemVos = tempCarts.stream().map(po -> JSON.parseObject(po.toString(), CartItemVo.class)).toList();
                for (CartItemVo tempItem : tempCartItemVos) {
                    //更新内容 ,判断用户的购物车和临时的购物车是否商品对等：如果不对等直接合并缓存，如果对等修改后合并缓存
                    cartItemVos.add(addCart(tempItem.getSkuId(), tempItem.getCount(), true, tempItem));
                }
                //删除临时内容
                deleteTempCarts(userKey);
                cartVo.setItems(cartItemVos);
                return cartVo;
            } else {
                //没有
                String user = CART_REDIS_HASH_KEY + tempOrInfoUserTo.getUserId();
                BoundHashOperations<String, Object, Object> ops = stringRedisTemplate.boundHashOps(user);
                List<Object> carts = ops.values();
                if (MyCollUtil.isNotEmpty(carts)) {
                    List<CartItemVo> itemVos = carts.stream().map(po -> JSON.parseObject(po.toString(), CartItemVo.class)).toList();
                    cartVo.setItems(itemVos);
                    return cartVo;
                }
            }
        } else {
            //没登录直接查询出返回
            BoundHashOperations<String, Object, Object> tempOps = getHashOps();
            List<Object> temp = tempOps.values();
            if (MyCollUtil.isNotEmpty(temp)) {
                List<CartItemVo> tempVos = temp.stream().map(po -> JSON.parseObject(po.toString(), CartItemVo.class)).toList();
                cartVo.setItems(tempVos);
                return cartVo;
            }
        }

        return null;
    }

    /**
     * @param skuId
     * @param checkedNum
     * @return void
     * @description 修改选中字段
     * @author zhangyiheng
     * @date 2024/6/29 13:22
     */
    @Override
    public void checked(Long skuId, Integer checkedNum) {
        BoundHashOperations<String, Object, Object> ops = getHashOps();

        Object cart = ops.get(skuId.toString());
        CartItemVo cartItemVo = JSON.parseObject(cart.toString(), CartItemVo.class);
        cartItemVo.setSelected(checkedNum == 1);

        ops.put(cartItemVo.getSkuId().toString(), JSON.toJSONString(cartItemVo));
    }

    @Override
    public void onOutNum(Long skuId, Integer count) {
        BoundHashOperations<String, Object, Object> ops = getHashOps();

        Object cart = ops.get(skuId.toString());
        CartItemVo cartItemVo = JSON.parseObject(cart.toString(), CartItemVo.class);
        cartItemVo.setCount(count);

        ops.put(cartItemVo.getSkuId().toString(), JSON.toJSONString(cartItemVo));
    }

    @Override
    public void delete(Long skuId) {
        BoundHashOperations<String, Object, Object> ops = getHashOps();
        ops.delete(skuId.toString());
    }

    @Override
    public List<CartItemVo> getMemberCarts() {
        TempOrInfoUserTo tempOrInfoUserTo = TempOrInfoUserInterceptor.threadLocal.get();
        if (Objects.isNull(tempOrInfoUserTo)){
            return null;
        }
        BoundHashOperations<String, Object, Object> ops = getHashOps();
        List<Object> values = ops.values();
        if (MyCollUtil.isNotEmpty(values)) {
            return values.stream()
                    .map(po -> JSON.parseObject(po.toString(), CartItemVo.class))
                    .filter(CartItemVo::getSelected)
                    //重新查询价格
                    .peek(po -> po.setPrice(productFeignService.getPrice(po.getSkuId())))
                    .toList();
        }
        return null;
    }

    private BoundHashOperations<String, Object, Object> getHashOps() {
        TempOrInfoUserTo tempOrInfoUserTo = TempOrInfoUserInterceptor.threadLocal.get();
        String key = "";
        if (!Objects.isNull(tempOrInfoUserTo.getUserId())) {
            key = CART_REDIS_HASH_KEY + tempOrInfoUserTo.getUserId();
        } else {
            key = CART_REDIS_HASH_KEY + tempOrInfoUserTo.getUserKey();
        }
        return stringRedisTemplate.boundHashOps(key);
    }

    public void deleteTempCarts(String userKey) {
        stringRedisTemplate.delete(userKey);
    }
}
